package ext.tianma.project2.APQP.service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.rmi.RemoteException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFHyperlink;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.util.CellRangeAddress;
import org.dom4j.DocumentException;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.remoting.support.RemoteAccessor;
import org.springframework.stereotype.Service;

import wt.fc.ObjectReference;
import wt.fc.PagingQueryResult;
import wt.fc.PagingSessionHelper;
import wt.fc.PersistenceHelper;
import wt.fc.PersistenceServerHelper;
import wt.fc.QueryResult;
import wt.fc.ReferenceFactory;
import wt.fc.collections.WTHashSet;
import wt.inf.container.OrgContainer;
import wt.inf.container.WTContainerHelper;
import wt.inf.team.ContainerTeamHelper;
import wt.inf.team.ContainerTeamManagedInfo;
import wt.inf.team.ContainerTeamManagedState;
import wt.inf.template.DefaultWTContainerTemplate;
import wt.org.WTOrganization;
import wt.org.WTUser;
import wt.part.WTPart;
import wt.projmgmt.admin.ProjAdminHelper;
import wt.projmgmt.admin.Project2;
import wt.projmgmt.admin.ProjectHealthStatus;
import wt.query.QuerySpec;
import wt.query.SearchCondition;
import wt.session.SessionHelper;
import wt.type.ClientTypedUtility;
import wt.type.TypeDefinitionForeignKey;
import wt.type.TypeDefinitionReference;
import wt.type.Typed;
import wt.type.TypedUtility;
import wt.util.WTException;
import wt.util.WTProperties;
import wt.util.WTPropertyVetoException;
import wt.vc.config.LatestConfigSpec;
import wt.vc.views.View;
import wt.vc.views.ViewHelper;

import com.ptc.core.lwc.server.PersistableAdapter;
import com.ptc.projectmanagement.plan.Plan;
import com.ptc.projectmanagement.plan.PlanActivity;
import com.ptc.projectmanagement.plan.PlanHelper;
import com.ptc.projectmanagement.plan.PlannableState;

import ext.com.iba.IBAUtil;
import ext.generic.erp.common.CommonPDMUtil;
import ext.tianma.bom.util.EnumerationUtil;
import ext.tianma.model.APQPSequence;
import ext.tianma.project2.APQP.constants.APQPProjectConstant;
import ext.tianma.project2.util.ProjectUtil;
import ext.tianma.util.TMUtil;
import ext.tianma.util.UserUtil;

@Service
public class APQPProjectService extends RemoteAccessor{
	
	@Autowired
	APQPPlanActivityService planactivityservice;
	
	@Autowired
	ProcessService processservice;
	
	//AQPQ项目的标准属性，请不要改变属性顺序
	private static final String[] PROJECT_MDA_ATTRS = {"productType","customerName","productUse","pm",
			"modelName","requirement","share","shareNum","differences",
			"lcmSite","quality","standard","checkBack", "evaluationiTme"};
	
	//APQP枚举：  key：标准属性key   value：枚举名称key
	private static Map<String,String> PROJECT_ENUM_ATTRS2 = new HashMap<String, String>();
	
	//用户
	private static List<String> PROJECT_USER_ATTRS2 = new ArrayList<String>();
	
	//导出项目时，表格列与变量名的关系，有顺序的
	private static Map<String,String> PROJECT_TABLE_MAP = new LinkedHashMap<String,String>();
	
	//apqp随机序列长度serialNumber
	private static final Integer SERIALLENGTH = 3;
	
	//导出报表，各SQE完成时的显示值
	private static final String SQE_STATUS = PlannableState.COMPLETED.getDisplay(Locale.getDefault());
	
	private static String HTTP = null; 
	private static String HOSTNAME = null;
	private static String CODEBASE_LOCATION = null;
	
	/** 
	 * 导出报表时，各SQE完成情况的颜色
	 * 未开始：黄色
	 * 未上载：橘色
	 * 延     期：红色
	 * 已完成：绿色
    */
	private static final String [] colors = {"YELLOW", "TAN", "RED", "GREEN"};
	
	/**查看项目时，各自状态下，额外返回的数据格式
	 * 0：单纯的查看某个项目详情，默认为此情况，不含任务信息
	 * 1：搜索项目表格时，展示项目的属性，含任务，所有任务合并成一条数据展示
	 * 2：导出项目Excel时，按照指定格式导出，含任务，各任务按照阶段展示
	 * */
	public static final String [] READPROJECTTYPE = {"0","1","2"};
	
	static {
		
		try {
			WTProperties props = WTProperties.getLocalProperties();
			HTTP = props.getProperty("wt.webserver.protocol");
			HOSTNAME = props.getProperty("java.rmi.server.hostname");
			CODEBASE_LOCATION = props.getProperty("wt.codebase.location");
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		
		//标准属性中，是用户信息的
		PROJECT_USER_ATTRS2.add("pm");
		
		//标准属性中，是枚举信息的
		PROJECT_ENUM_ATTRS2.put("share", "isBoolean");
		PROJECT_ENUM_ATTRS2.put("standard", "standard");
		PROJECT_ENUM_ATTRS2.put("checkBack", "isBoolean");
		
		//导出项目时，项目信息的表头列：key：表头列名称，  value：属性内部名称
		PROJECT_TABLE_MAP.put("序号", "num");
		PROJECT_TABLE_MAP.put("项目编号", "projectName");
		PROJECT_TABLE_MAP.put("产品类型", "productType");
		PROJECT_TABLE_MAP.put("当前状态", "state");
		PROJECT_TABLE_MAP.put("OEM/产品用途/生命周期", "productUse");
		PROJECT_TABLE_MAP.put("PM", "pm");
		PROJECT_TABLE_MAP.put("机型名称", "modelName");
		PROJECT_TABLE_MAP.put("是否有沿用/共用/共模", "share");
		PROJECT_TABLE_MAP.put("沿用/共用/共模的机型&料号", "shareNum");
		PROJECT_TABLE_MAP.put("具体差异点", "differences");
		PROJECT_TABLE_MAP.put("LCM产地", "lcmSite");
		PROJECT_TABLE_MAP.put("质量目标", "quality");
		PROJECT_TABLE_MAP.put("通用标准（QDS）/特殊购规", "standard");
	}
	
	/**
	 * 创建/更新项目
	 * @param params
	 * @return
	 * @throws JSONException
	 * @author xucr
	 * @CreateDate 2020年8月13日
	 */
	public JSONObject createAPQP(String params) throws JSONException {
		JSONObject result = new JSONObject();
		try {
			WTUser user = (WTUser) SessionHelper.manager.getPrincipal();
			boolean iscreate = ProjectUtil.isGroupUser(user, APQPProjectConstant.AQPQ_BUSINESS_ADMINISTRATOR);
			/**
			 * 当存在projectOid时，更新项目
			 * 	1. 更新时，没有继续保存草稿动作
			 *  2. 当是草稿更新时：
			 *  	修改项目状态为进行中
			 * 	3. 当存在活动时
			 * 		更新项目、更新活动
			 *  4. 当不存在活动时
			 *  	更新项目、创建活动
			 * 
			 * 否则创建项目
			 * 	1.保存：草稿，机型名称必填+活动必须有数据
			 *  2.创建：创建实际对象，所有内容必填
			 *  
			 * 校验
			 *  1. 只有APQP业务管理员群组成员能创建
			 *  2. 机型名称存在的话，则不允许创建
			 *  
			 * */
			if(!iscreate) {
				result.put("msg", APQPProjectConstant.TIP1);
				result.put("code", "1");
			} else {
				Project2 project2 = null;
				JSONObject paramsObj = new JSONObject(params);
				JSONObject projectBean = paramsObj.getJSONObject("projectBean");
				//原有的活动
				JSONArray planBean = null;
				if(paramsObj.has("planBean")) {
					planBean = paramsObj.getJSONArray("planBean");
				} else {
					planBean = new JSONArray();
				}
				
				boolean isCreate = false;
				if(projectBean.has("projectOid")) {
					String projectOid = projectBean.getString("projectOid"); //项目oid，当存在时，则为更新
					if(StringUtils.isNotEmpty(projectOid)) {
						project2 = (Project2) TMUtil.oid2Obj(projectOid);
						/**
						 * 除已关闭的项目外，均可以编辑项目+活动
						 * 
						 * 1、编辑项目
						 * 	  进行中：编辑项目信息
						 *   草    稿：编辑项目信息，并且状态变为进行中
						 * 2、同步活动
						 * 	 add：创建活动，并且修改项目状态为进行中
						 *   del：删除该活动
						 *   ude：更新活动
						 * */
						ContainerTeamManagedState state = null;
						if(ContainerTeamManagedState.DEFINED.equals(project2.getContainerTeamManagedInfo().getState())) {
							state = ContainerTeamManagedState.RUNNING;
						}
						
						//增加的数据
						JSONArray addPlanBean = null;
						if(paramsObj.has("addPlanBean")) {
							addPlanBean = paramsObj.getJSONArray("addPlanBean");
						}
						
						//删除的数据
						String delPlans = "";
						if(paramsObj.has("delPlans")) {
							JSONArray delPNs = paramsObj.getJSONArray("delPlans");
							if(null != delPNs && delPNs.length() > 0) {
								for(int i = 0 ; i < delPNs.length(); i++) {
									delPlans += delPNs.getString(i) + ",";
								}
							}
						}
						
						//创建新增的： 有新的活动创建时，项目则需要变为进行中
						if(null != addPlanBean && addPlanBean.length() > 0) {
							state = ContainerTeamManagedState.RUNNING;
							String [] phases = planactivityservice.getPhase(project2);
							planactivityservice.batchCreatePlanActivity(project2, addPlanBean, phases);
						}
						
						//更新原有的
						if(null != planBean && planBean.length() > 0) {
							planactivityservice.batchUpdaatePlanActivity(project2, planBean);
						}
						
						//删除移除的
						WTHashSet set = new WTHashSet();
						if(StringUtils.isNotEmpty(delPlans)) {
							JSONObject pa = new JSONObject();
							pa.put("pn", delPlans);
							QuerySpec qs = ProjectUtil.queryPlanActivityByParams(project2, pa);
							QueryResult qr = PersistenceHelper.manager.find(qs);
							while(qr.hasMoreElements()) {
								Object [] obj = (Object[]) qr.nextElement();
								PlanActivity plan = (PlanActivity) obj[0];
								set.add(plan);
							}
						}
						if(set.size() > 0) {
							PersistenceServerHelper.manager.remove(set);
							
							//当存在删除时，检验剩余任务是否都关闭了，若是，则直接关闭项目
							boolean isClosedProject = isClosedProject(project2);
							if(isClosedProject) {
								state = ContainerTeamManagedState.COMPLETED;
							}
						}
						
						updateProject(project2, projectBean, state);
						result.put("msg", "");
						result.put("code", "0");
					} else {
						isCreate = true;
					}
				} else {
					isCreate = true;
				}
				
				if(isCreate) {
					//校验机型名称：已在选择时实施校验
					String isDraft = paramsObj.getString("isDraft");
					if("true".equals(isDraft)) {//草稿
						project2 = createProject(projectBean, 
								APQPProjectConstant.APQP_TEMPLATE_NAME, ContainerTeamManagedState.DEFINED, true);
					} else {
						project2 = createProject(projectBean, 
								APQPProjectConstant.APQP_TEMPLATE_NAME, ContainerTeamManagedState.RUNNING, false);
					}
					String [] phases = planactivityservice.getPhase(null);
					planactivityservice.batchCreatePlanActivity(project2, planBean, phases);
					result.put("msg", "");
					result.put("code", "0");
				}
			}
		} catch (WTException e) {
			e.printStackTrace();
			logger.error("createAPQP >>>catch1 >>>>>: " + e.getLocalizedMessage(Locale.getDefault()));
			result.put("msg", APQPProjectConstant.TIP2);
			result.put("code", "1");
		} catch (WTPropertyVetoException e) {
			e.printStackTrace();
			logger.error("createAPQP >>>catch2 >>>>>: " + e.getLocalizedMessage(Locale.getDefault()));
			result.put("msg", APQPProjectConstant.TIP2);
			result.put("code", "1");
		} catch (IOException e) {
			e.printStackTrace();
			logger.error("createAPQP >>>catch3 >>>>>: " + e.getLocalizedMessage());
			result.put("msg", APQPProjectConstant.TIP2);
			result.put("code", "1");
		} catch (DocumentException e) {
			e.printStackTrace();
			logger.error("createAPQP >>>catch4 >>>>>: " + e.getLocalizedMessage());
			result.put("msg", APQPProjectConstant.TIP2);
			result.put("code", "1");
		}
		return result;
	}
	
	/**
	 * 判断是否能够关闭项目
	 * @param project
	 * @return
	 * @throws JSONException
	 * @author xucr
	 * @CreateDate 2020年10月13日
	 */
	public boolean isClosedProject (Project2 project) throws JSONException {
		/**
		 * 即：没有进行中的任务
		 */
		boolean isTrue = false;
		JSONObject queryParams = new JSONObject();
		queryParams.put("isStandard", APQPProjectConstant.NO);
		try {
			QuerySpec qs = ProjectUtil.queryPlanActivityByParams(project, queryParams);
			QueryResult qr = PersistenceHelper.manager.find(qs);
			if(qr.size() <= 0) {
				isTrue = true;
			}
		} catch (WTException e) {
			e.printStackTrace();
		}
		return isTrue;
	}
	
	/**
	 * 创建项目
	 * @param bean
	 * @param templateName
	 * @param state
	 * @param isDraf
	 * @return
	 * @throws Exception
	 * @author xucr
	 * @throws WTPropertyVetoException 
	 * @throws IOException 
	 * @throws JSONException 
	 * @CreateDate 2020年8月13日
	 */
	private Project2 createProject(JSONObject projectBean, String templateName, ContainerTeamManagedState state, boolean isDraf) throws WTException, WTPropertyVetoException, IOException, JSONException {
		//组织
		WTUser user = (WTUser) SessionHelper.manager.getPrincipal();
        WTOrganization wtorg = user.getOrganization();
		OrgContainer org = WTContainerHelper.service.getOrgContainer(wtorg);
		if(null == org) {
			throw new WTException("上下文不存在");
		}
		
		//项目模板:站点
//		DefaultWTContainerTemplate d = (DefaultWTContainerTemplate) ContainerTemplateHelper.service.getContainerTemplate(
//				WTContainerHelper.getExchangeRef(), templateName, Project2.class);
		
		//项目模板：组织
		DefaultWTContainerTemplate d = getProjectTemplate(templateName);
		if(null == d) {
			throw new WTException("不存在名称为【" + templateName + "】的项目模板");
		}
		
		Project2 project = Project2.newProject2();
		String apqpName = initAPQPSequence();
		project.setName(apqpName);
		project.setContainer(org);
		project.setCreator(user);
		project.setOwner(user);
		project.setSharingEnabled(true);
		project.setContainerTemplate(d);
		ContainerTeamManagedInfo ctinfo = ContainerTeamManagedInfo.newContainerTeamManagedInfo();
		//设置状态
		ctinfo.setState(state);
		project.setContainerTeamManagedInfo(ctinfo);
		// 设置软类型
		setSoftType(project, APQPProjectConstant.APQP_PROJECT);
		
		//扩展
		project.setHealthStatus(ProjectHealthStatus.GREEN);
		project.setPseudoType(1);
		
		project = ProjAdminHelper.service.create(project);
		
		if(!isDraf) {
			ContainerTeamHelper.service.activate(project);//此动作会将项目变为进行中
		}
		
		//团队在模板中已定义好，这里不处理
		
		//设置标准属性
		setProjectSTDAttr(project, projectBean);
		project = (Project2) PersistenceHelper.manager.refresh(project);
		
//		HashMap<String,Object> data=new HashMap<String, Object>();
//		ReferenceFactory rf = new ReferenceFactory();
//	    String curProcessOid = rf.getReferenceString(project);
//		data.put("projectOid", curProcessOid);
		
		return project;
	}
	
	/**
	 * 获取组织下的项目模板
	 * @param templateName
	 * @return
	 * @throws WTException
	 * @author xucr
	 * @CreateDate 2020年9月28日
	 */
	public DefaultWTContainerTemplate getProjectTemplate(String templateName) throws WTException {
		DefaultWTContainerTemplate result = null;
		QuerySpec qs = new QuerySpec();
		int tid = qs.appendClassList(DefaultWTContainerTemplate.class, true);
		SearchCondition eq_name = new SearchCondition(DefaultWTContainerTemplate.class, DefaultWTContainerTemplate.NAME, SearchCondition.EQUAL,
				templateName);
		qs.appendWhere(eq_name, new int[] { tid });
		QueryResult qr = PersistenceHelper.manager.find(qs);
		if (qr.hasMoreElements()) {
			Object[] o = (Object[]) qr.nextElement();
			result = (DefaultWTContainerTemplate) o[tid];
		}
		return result;
	}
	
	/**
	 * 更新项目
	 * @param project
	 * @param projectBean
	 * @param state
	 * @return
	 * @throws WTException
	 * @throws WTPropertyVetoException
	 * @throws IOException
	 * @throws JSONException
	 * @author xucr
	 * @CreateDate 2020年9月7日
	 */
	public Project2 updateProject(Project2 project, 
			JSONObject projectBean, ContainerTeamManagedState state) throws WTException, WTPropertyVetoException, IOException, JSONException {
		
		project = (Project2) PersistenceHelper.manager.refresh(project);
		
		if(null != state) {
			ContainerTeamManagedInfo ctinfo = project.getContainerTeamManagedInfo();
			//设置状态
			ctinfo.setState(state);
			project.setContainerTeamManagedInfo(ctinfo);
		}
		
		//设置标准属性
		setProjectSTDAttr(project, projectBean);
		project = (Project2) PersistenceHelper.manager.refresh(project);
		
		return project;
	}
	
	/**
	 * 设置标准属性
	 * @param project
	 * @param projectBean
	 * @throws IOException
	 * @throws WTException
	 * @author xucr
	 * @throws JSONException 
	 * @CreateDate 2020年8月13日
	 */
	private void setProjectSTDAttr(Project2 project, JSONObject projectInfo) throws IOException, WTException, JSONException {
		PersistableAdapter pa = new PersistableAdapter(project, APQPProjectConstant.APQP_PROJECT, SessionHelper.getLocale(), null);
		pa.load(Arrays.asList(PROJECT_MDA_ATTRS));//必须要先load再set
		
		for(int i = 0 ; i < PROJECT_MDA_ATTRS.length; i++) {
			if(projectInfo.has(PROJECT_MDA_ATTRS[i])){
				String key = PROJECT_MDA_ATTRS[i];
				String value = projectInfo.getString(PROJECT_MDA_ATTRS[i]);
				
				//标准属性为用户类型时，保存用户名，保证唯一性
				if(PROJECT_USER_ATTRS2.contains(key)) {
					List<WTUser> users = ProjectUtil.getUserList(value);
					if(users.size() > 0) {
						WTUser user = users.get(0);
						if(null != user) {
							value = user.getName();
						}
					}
				}
				pa.set(key, value);
			}
		}
		pa.validate();
		pa.apply();
		PersistenceHelper.manager.save(project);
	}
	
	/**
	 * 查询标准属性
	 * @param project
	 * @param projectInfo
	 * @throws IOException
	 * @throws WTException
	 * @throws JSONException
	 * @author xucr
	 * @CreateDate 2020年8月25日
	 */
	public void getProjectSTDAttr(Project2 project, String [] stdAttrs, JSONObject result) throws IOException, WTException, JSONException {
		if(null == stdAttrs || stdAttrs.length <= 0) {
			stdAttrs = PROJECT_MDA_ATTRS;
		}
		PersistableAdapter pa = new PersistableAdapter(project, APQPProjectConstant.APQP_PROJECT, SessionHelper.getLocale(), null);
		pa.load(Arrays.asList(stdAttrs));//必须要先load再set
		
		for(int i = 0 ; i < stdAttrs.length; i++) {
			String key = stdAttrs[i];
			String value = (String) pa.get(key);
//			//应前端要求，项目的枚举值，返回枚举key即可，无需 返回value
//			if(PROJECT_ENUM_ATTRS2.containsKey(key)) {//如果是枚举
//				Map<String,String> maps = EnumerationUtil.getEnumerationValues(PROJECT_ENUM_ATTRS2.get(key));
//				value = maps.get(value);
//			}
			//展示处理标准属性是用户的
			if(PROJECT_USER_ATTRS2.contains(key) && StringUtils.isNotEmpty(value)) {
				WTUser user = UserUtil.getUserByName(value);
				if(null != user) {
					value = user.getFullName();
				}
			}
			result.put(key, value);
		}
	}
	
	/**
	 * 按条件搜索APQP，并封装数据
	 * @param params
	 * @throws JSONException
	 * @throws WTException
	 * @author xucr
	 * @throws IOException 
	 * @CreateDate 2020年8月24日
	 */
	public JSONObject queryAPQPs(String params) throws JSONException, WTException, IOException {
		JSONObject obj = new JSONObject(params);
		QuerySpec qs = ProjectUtil.queryAPQPsByParams(obj, APQPProjectConstant.APQP_PROJECT);
		Integer page = 1;
		Integer limit = 10;
		
		if(obj.has("page")) {
			page = obj.getInt("page");
		}
		if(obj.has("limit")) {
			limit = obj.getInt("limit");
		}
		
		//分页查询
	    PagingQueryResult qr = PagingSessionHelper.openPagingSession((page - 1) * limit, limit, qs);
	    JSONArray array = new JSONArray();
	    WTUser u = (WTUser) SessionHelper.manager.getPrincipal();
	    List<Project2> projects = new ArrayList<Project2>();
	    int repeatNum = 0;//重复的数量
	    while (qr.hasMoreElements()) {
	    	Object [] o = (Object []) qr.nextElement();
	    	Project2 project = (Project2) o[0];
	    	if(!projects.contains(project)) {
	    		array.put(findAPQP(project, u, APQPProjectService.READPROJECTTYPE[1]));
	    		projects.add(project);
	    	} else {
	    		repeatNum ++;
	    	}
	    }
	    //可能存在一个项目对应多个相同条件的任务，因此，这里需要统计相同项目的量，然后在总量中减掉
	    JSONObject result = ProjectUtil.respInfo(array, qr.getTotalSize() - repeatNum);
		return result;
	}
	
	/**
	 * 查询项目详情1
	 * @param projectOid
	 * @param sessionUser 当前登陆者
	 * @return
	 * @throws WTException
	 * @throws JSONException
	 * @author xucr
	 * @throws IOException 
	 * @CreateDate 2020年8月24日
	 */
	public JSONObject findAPQP(String projectOid, WTUser sessionUser, String readType) throws WTException, JSONException, IOException {
		Project2 project = (Project2) TMUtil.oid2Obj(projectOid);
		JSONObject result = findAPQP(project, sessionUser, readType);
		return result;
	}
	
	/**
	 * 查询项目详情2
	 * @param project
	 * @param sessionUser 当前登陆者
	 * @return
	 * @throws WTException
	 * @throws JSONException
	 * @author xucr
	 * @throws IOException 
	 * @CreateDate 2020年8月24日
	 */
	@SuppressWarnings("deprecation")
	public JSONObject findAPQP(Project2 project, WTUser sessionUser, String readType) throws WTException, JSONException, IOException {
		JSONObject result = new JSONObject();
		
		if(null != project) {
			String projectName = project.getName();
			String owner = ((WTUser )project.getOwner()).getFullName();
			result.put("projectName", projectName);
			result.put("owner", owner);
			result.put("projectOid", TMUtil.obj2Oid(project));
			result.put("state", project.getContainerTeamManagedInfo().getState());
			if(ContainerTeamManagedState.DEFINED.equals(project.getContainerTeamManagedInfo().getState())) {
				result.put("stateZH", "草稿");
			} else {
				result.put("stateZH", project.getContainerTeamManagedInfo().getState().getDisplay(Locale.CHINA));
			}
			
//			//材评时间：原来取至第一次审批时间，变更为取APQP项目标准属性：材评时间
//			String processCreateTime = "";
//			FormDataXml xml = processservice.getFirstProcess(project);
//			if(null != xml) {
//				WfProcess process = (WfProcess) xml.getProcess().getObject();
//				processCreateTime = TMUtil.timestampToString(process.getCreateTimestamp(),"yyyy-MM-dd");
//			}
//			result.put("processCreateTime", processCreateTime);
			
			boolean iscreate = ProjectUtil.isGroupUser(sessionUser, APQPProjectConstant.AQPQ_BUSINESS_ADMINISTRATOR);
			QuerySpec qs = ProjectUtil.queryFormDataXml(null, project, APQPProjectConstant.FORMDATA_STATUS_POTENTIAL);
		    QueryResult qr = PersistenceHelper.manager.find(qs);
		    /**
		     * isOwner + processing 两条属性，用于在前端判断当前登陆者能否编辑APQP
		     * */
//			result.put("isOwner", sessionUser.equals(project.getOwner()) ? true : false);//仅创建者有权限
			result.put("isOwner", iscreate ? true : false);//该组下成员有权限
			result.put("processing", qr.size() > 0 ? true : false); //是否存在进行中的流程
			
			getProjectSTDAttr(project, null, result);
			
			//按照首页搜索apqp展示数据
			String [] stdAttrs = {"materialCategory","pn","supplier","isUpload","isStandard","apqp"};
			if(READPROJECTTYPE[1].equals(readType)) {
				Plan plan = (Plan) PlanHelper.service.getPlan(ObjectReference.newObjectReference(project));
				List<PlanActivity> plans = ProjectUtil.getAllChildren(plan);
				for(PlanActivity pa : plans) {
					planactivityservice.getPlanactivitySTDAttr2(pa, stdAttrs, result);
				}
			} 
			//按照首页导出apqp展示数据
			else if(READPROJECTTYPE[2].equals(readType)) {
				Plan plan = (Plan) PlanHelper.service.getPlan(ObjectReference.newObjectReference(project));
				List<PlanActivity> plans = ProjectUtil.getAllChildren(plan);
				/**
				 * Map<String, Map<String,String>> maps
				 * 外层：key 阶段，  value ：阶段的所有任务
				 * 内层：key 各属性key， value：各属性value
				 * */
				JSONObject all = null;
				JSONObject one = null;
				JSONObject two = null;
				String [] atts = {"materialCategory"};
				Date tempDate = new Date();
				Timestamp startDate = null;
				JSONArray array = null; //某个阶段所有的内容集合，且相同物料类别合并
				for(PlanActivity pa : plans) {
					one = new JSONObject();
					all = new JSONObject();
					array = new JSONArray();
					List<PlanActivity> childs = ProjectUtil.getAllChildren(pa);
					planactivityservice.getPlanactivitySTDAttr(pa, atts, one);
					for(PlanActivity cpa : childs) {
						two = new JSONObject();
						
						two.put("owner", cpa.getOwnership().getOwner().getFullName());
						two.put("startDate", TMUtil.timestampToString(cpa.getStartDate(),"yyyy-MM-dd"));
						
						planactivityservice.getPlanactivitySTDAttr(cpa, stdAttrs, two);
						planactivityservice.findDelivery(cpa, two, true, false);
						
						/** 
						 * 未开始：黄色
						 * 未上载：橘色
						 * 延     期：红色
						 * 已完成：绿色
						 */
						startDate = cpa.getStartDate();
						if(PlannableState.SCHEDULED.equals(cpa.getPlannableState())) {
							two.put("completionStatus", colors[0]);
						} else if(PlannableState.INPROCESS.equals(cpa.getPlannableState())) {
							//已达标，即使任务未关闭，也归纳到完成行列
							if(APQPProjectConstant.YES.equals(two.getString("isStandard"))
									|| APQPProjectConstant.YES_VALUE.equals(two.getString("isStandard"))) {
								two.put("completionStatus", colors[3]);
							} else {
								if(tempDate.before(startDate)) {//------计划时间--------当前时间-------->
									//正常
									two.put("completionStatus", colors[1]);
								} else {
									//延期
									two.put("completionStatus", colors[2]);
								}
							}
						} else if(PlannableState.COMPLETED.equals(cpa.getPlannableState())) {
							two.put("completionStatus", colors[3]);
						}
						two.put("startDate", TMUtil.timestampToString(startDate,"yyyy-MM-dd"));
						all.put(two.getString("apqp"), two);
					}
					array.put(all);
					if(!result.has(one.getString("materialCategory").split(APQPPlanActivityService.MATERIALCATEGORY_SPLIT)[0].trim())) {
						result.put(one.getString("materialCategory").split(APQPPlanActivityService.MATERIALCATEGORY_SPLIT)[0].trim(), array);
					} else {
						array = result.getJSONArray(one.getString("materialCategory").split(APQPPlanActivityService.MATERIALCATEGORY_SPLIT)[0].trim());
						array.put(all);
						result.put(one.getString("materialCategory").split(APQPPlanActivityService.MATERIALCATEGORY_SPLIT)[0].trim(), array);
					}
				}
			}
		}
		return result;
	}
	
//	//Ireport导出方式
//	public String exportExcel() {
//		Map<String,Object> parameters = new HashMap<String,Object>();
//		
//		String path = IReportService.writeIRPDF(parameters);
//		
//		return path;
//	}
	
	/**
	 * 导出数据到Excel(含子计划)
	 * @param array
	 * @return
	 * @throws IOException
	 * @throws JSONException
	 * @throws DocumentException
	 * @author xucr
	 * @CreateDate 2020年9月3日
	 */
	public String exportExcel(JSONArray array) throws IOException, JSONException, DocumentException {
		
		String filePath =CODEBASE_LOCATION + File.separator + "temp" + File.separator + "APQP" + File.separator + "report";
		File targerFile = new File(filePath);
		if(!targerFile.exists()) {
			targerFile.mkdirs();
		}
		String pathAndName = filePath + File.separator + "APQP.xls";
		
		String domain = HTTP + "://" + HOSTNAME + File.separator + "Windchill";
		String realPath = domain + File.separator + "temp" + File.separator + "APQP" + File.separator + "report" + File.separator + "APQP.xls";
		
		//1.创建HSSFWorkbook,对应一个excel
		HSSFWorkbook wb = new HSSFWorkbook();
		
		//2.在workbook中创建一个sheet，对应excel中的sheet
		HSSFSheet sheet = wb.createSheet("APQP报表信息");
		HSSFSheet sheet2 = wb.createSheet("颜色说明");
		
		//3.1在sheet中添加表头:0 一级title，1二级title
		HSSFRow row = sheet.createRow(0);
		HSSFRow row1 = sheet.createRow(1);
		//3.2在sheet2中添加表头：颜色说明
		HSSFRow row2 = sheet2.createRow(0);
		
		//4 创建单元格：表头居中
	    HSSFCellStyle cellStyle = initCellStyle(wb, (short)0);
	    
	    Map<String, HSSFCellStyle> colorMap = initCellColor(wb);
	    
 		// 创建标题:项目标题
	 	Map<Integer,String> titleKey = new LinkedHashMap<Integer,String>();
	 	writeProjectTitle(sheet, row, cellStyle, titleKey);
 		
 		//创建标题：活动一级标题
 		String materialCategory = APQPConfig.getKey("MaterialCategory");
 		String addTitle = "P/N;Supplier;SQE";
 		String phaseKey = addTitle + APQPProjectConstant.SPLITVALUE + APQPConfig.getKey("phase");//二级title列
 		
 		//创建活动标题
 		writeActivityTitle(sheet, row, row1, cellStyle, materialCategory, phaseKey);
 		
 		//创建颜色说明
 		writeColorRemark(wb, row2, cellStyle);
 		
 		//创建内容
 		int maxRow = 0; //每条项目中，最多阶段活动的行数，用于定义项目开始写入行数
 		int actStartRow = 0;
 		for(int i =0; i<array.length(); i++) {//数据行
 			JSONObject jsonObject = array.getJSONObject(i);
 			
 			//计算每行数据开始行
 			if(i == 0) {
 				actStartRow = i+2;
 			} else {
 				actStartRow += maxRow;
 			}
 			
 			//创建活动内容，返回阶段最多的数，用于下一条数据写到第几行
 			maxRow = writeActivityData(materialCategory, addTitle, phaseKey, jsonObject, actStartRow, sheet, colorMap);
 			
 			//创建项目内容
 			writeProjectData(jsonObject, actStartRow, maxRow, sheet, cellStyle, (i+1), titleKey);
 		}
 		
        FileOutputStream os = new FileOutputStream(pathAndName);
        wb.write(os);
		os.flush();
		os.close();
		return realPath;
	}
	
	/**
	 * 封装物料类别
	 * @author xucr
	 * @throws JSONException 
	 * @CreateDate 2020年9月29日
	 */
	public JSONObject getMaterialCategory() throws JSONException {
		JSONObject result = null;
		try {
			String materialCategory = APQPConfig.getKey("MaterialCategory");
			JSONArray array = new JSONArray();
			if(StringUtils.isNotEmpty(materialCategory)) {
				String [] materialCategorys = materialCategory.split(APQPProjectConstant.SPLITVALUE);
				JSONObject obj = null;
				for(String category : materialCategorys) {
					obj = new JSONObject();
					obj.put("key", category);
					obj.put("value", category);
					array.put(obj);
				}
			}
			result = ProjectUtil.respInfo(array, array.length());
		} catch (DocumentException | IOException e) {
			result = new JSONObject();
			e.printStackTrace();
			logger.error("getMaterialCategory >>>catch1 >>>>>: " + e.getLocalizedMessage());
			result.put("msg", e.getLocalizedMessage());
			result.put("code", "1");
		} catch (JSONException e) {
			result = new JSONObject();
			e.printStackTrace();
			logger.error("getMaterialCategory >>>catch2 >>>>>: " + e.getLocalizedMessage());
			result.put("msg", e.getLocalizedMessage());
			result.put("code", "1");
		}
		return result;
	}
	
	/**
	 * 构造Excel单元格格式
	 * @param wb
	 * @param color
	 * @return
	 * @author xucr
	 * @CreateDate 2020年9月27日
	 */
	private HSSFCellStyle initCellStyle(HSSFWorkbook wb, short color) {
		HSSFCellStyle cellStyle = wb.createCellStyle();
	    cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);//水平居中
	    cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);//垂直居中
	    cellStyle.setWrapText(true);//设置Excel表格中\r\n换行
	    if(0 != color) {
	    	cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
			cellStyle.setFillForegroundColor(color);// 设置背景色
	    }
		return cellStyle;
	}
	
	/**
	 * 写项目信息标题
	 * @param sheet
	 * @param row
	 * @param cellStyle
	 * @param titleKey
	 * @author xucr
	 * @CreateDate 2020年9月25日
	 */
	private void writeProjectTitle(HSSFSheet sheet, HSSFRow row, HSSFCellStyle cellStyle, Map<Integer,String> titleKey) {
		int a = 0;
	 	CellRangeAddress c1 = null;
	 	HSSFCell cell = null;
 		for (String set : PROJECT_TABLE_MAP.keySet()) {
 			titleKey.put(a, PROJECT_TABLE_MAP.get(set));
 			cell = row.createCell(a);
 			cell.setCellValue(set);
 			cell.setCellStyle(cellStyle);
 			
 			//合并单元格
 			c1 = new CellRangeAddress(0, 1, a, a);
 			sheet.addMergedRegion(c1);
 			
 			a++;
 		}
	}
	/**
	 * 写项目信息内容
	 * @param jsonObject 数据
	 * @param startRow 开始行
	 * @param spanRow 跨多少行
	 * @param sheet
	 * @param cellStyle
	 * @param cellNum
	 * @param titleKey
	 * @throws JSONException
	 * @author xucr
	 * @CreateDate 2020年9月25日
	 */
	private void writeProjectData(JSONObject jsonObject, 
			int startRow, int spanRow, HSSFSheet sheet, HSSFCellStyle cellStyle, int cellNum, Map<Integer,String> titleKey) throws JSONException {
		HSSFCell cell = null;
		HSSFRow tempRow = null;
		for(int a = 0; a < spanRow; a++) {
			tempRow = sheet.getRow(startRow + a); //由于先写了活动，再写项目时，行已创建，直接获取即可，无需创建
			if(null == tempRow) {//有可能项目没有活动，这里需要创建行
				tempRow = sheet.createRow(startRow + a);
			}
			for(int j = 0 ; j < jsonObject.length(); j++) {//数据列
				if(j == 0) {//序号
					cell = tempRow.createCell(j);
					cell.setCellStyle(cellStyle);
					cell.setCellValue(cellNum);
					//合并单元格
					if(spanRow > 1) {//当为1时，说明有数据，但只有一条，没有合并，这里无需做合并处理
						//如果BLU有两个条，这里返回2，但合并时，不能用2，需要-1
						CellRangeAddress c1 = new CellRangeAddress(startRow, startRow + spanRow -1, j, j);
			 			sheet.addMergedRegion(c1);
					}
				} else {
					String key = titleKey.get(j);
	 				if(jsonObject.has(key)) {
		 				String value = "";
		 				cell = tempRow.createCell(j);
						cell.setCellStyle(cellStyle);
		 				if(PROJECT_ENUM_ATTRS2.containsKey(key)) {//如果是枚举
		 					Map<String,String> maps = EnumerationUtil.getEnumerationValues(PROJECT_ENUM_ATTRS2.get(key));
		 					String enumValue = jsonObject.getString(key);
		 					value = maps.get(enumValue);
		 				} else if("state".equals(key)) {
		 					value = jsonObject.getString("stateZH");
		 				} else {
		 					value = jsonObject.getString(key);
		 				}
		 	 			cell.setCellValue(value);
		 	 			//合并单元格
						if(spanRow > 1) {
							CellRangeAddress c1 = new CellRangeAddress(startRow, startRow + spanRow -1, j, j);
				 			sheet.addMergedRegion(c1);
						}
	 				}
				}
			}
		}
	}
	
	/**
	 * 写活动标题
	 * @param sheet
	 * @param row
	 * @param row1
	 * @param cellStyle
	 * @param materialCategory
	 * @param phaseKey
	 * @author xucr
	 * @CreateDate 2020年9月25日
	 */
	private void writeActivityTitle(HSSFSheet sheet, HSSFRow row, HSSFRow row1, HSSFCellStyle cellStyle, String materialCategory, String phaseKey) {
		String [] materialCategorys = materialCategory.split(APQPProjectConstant.SPLITVALUE);
 		String[] phaseKeys = phaseKey.split(APQPProjectConstant.SPLITVALUE);
 		
 		CellRangeAddress c2 = null;
 		int sss = phaseKeys.length;
 		HSSFCell cell = null;
 		int a = PROJECT_TABLE_MAP.size();
 		for(int j = 0 ; j < materialCategorys.length; j++) {
 			cell = row.createCell(a);
 			cell.setCellValue(materialCategorys[j].split(APQPPlanActivityService.MATERIALCATEGORY_SPLIT)[0].trim());
 			cell.setCellStyle(cellStyle);
 			
 			//创建标题：活动二级标题
 	 		for(int i = 0 ; i < phaseKeys.length; i++) {
 	 			cell = row1.createCell(a);
 	 			cell.setCellValue(phaseKeys[i]);
 	 			cell.setCellStyle(cellStyle);
 	 			
 	 			//每执行指定列后再合并一级菜单
 	 			if(sss % phaseKeys.length == 0) {
 	 				c2 = new CellRangeAddress(0, 0, a, a-1+phaseKeys.length);
 	 			}
 	 			sheet.addMergedRegion(c2);
 	 			sss ++;
 	 			a++;
 	 		}
 		}
	}
	
	/**
	 * 写颜色说明
	 * @param row2
	 * @param cellStyle
	 * @param cellStyle_SCHEDULED
	 * @param cellStyle_INPROCESS
	 * @param cellStyle_INPROCESS_DELAY
	 * @param cellStyle_COMPLETED
	 * @author xucr
	 * @CreateDate 2020年9月27日
	 */
	private void writeColorRemark(HSSFWorkbook wb, HSSFRow row2, HSSFCellStyle cellStyle) {
		
	    /** 4.2 设置各SQE完成情况的背景色
	     * 未开始：黄色
	     * 未上载：橘色
	     * 延     期：红色
	     * 已完成：绿色
	     * */
		Map<String, HSSFCellStyle> colorMap = initCellColor(wb);
	    HSSFCellStyle cellStyle_SCHEDULED = colorMap.get(colors[0]);
	    HSSFCellStyle cellStyle_INPROCESS = colorMap.get(colors[1]);
	    HSSFCellStyle cellStyle_INPROCESS_DELAY = colorMap.get(colors[2]);
	    HSSFCellStyle cellStyle_COMPLETED = colorMap.get(colors[3]);
		
 		String [] describe = {"未下发","未上载","延期未上载","已完成"};
 		
 		HSSFCell cell1 = row2.createCell(1);
 		cell1.setCellValue("各背景颜色说明");
		cell1.setCellStyle(cellStyle);
		
 		HSSFCell cell2 = row2.createCell(2);
 		cell2.setCellValue(describe[0]);
		cell2.setCellStyle(cellStyle_SCHEDULED);
		
 		HSSFCell cell3 = row2.createCell(3);
 		cell3.setCellValue(describe[1]);
		cell3.setCellStyle(cellStyle_INPROCESS);
		
 		HSSFCell cell4 = row2.createCell(4);
 		cell4.setCellValue(describe[2]);
		cell4.setCellStyle(cellStyle_INPROCESS_DELAY);
		
 		HSSFCell cell5 = row2.createCell(5);
		cell5.setCellValue(describe[3]);
		cell5.setCellStyle(cellStyle_COMPLETED);
	}
	
	/**
	 * 定义各种颜色说明
	 * @param wb
	 * @return
	 * @author xucr
	 * @CreateDate 2020年9月27日
	 */
	private Map<String, HSSFCellStyle> initCellColor(HSSFWorkbook wb) {
		/** 4.2 设置各SQE完成情况的背景色
	     * 未开始：黄色
	     * 未上载：橘色
	     * 延     期：红色
	     * 已完成：绿色
	     * */
		Map<String, HSSFCellStyle> colorMap = new HashMap<String, HSSFCellStyle>();
		HSSFCellStyle cellStyle_SCHEDULED = initCellStyle(wb, HSSFColor.YELLOW.index);
	    HSSFCellStyle cellStyle_INPROCESS = initCellStyle(wb, HSSFColor.TAN.index);
	    HSSFCellStyle cellStyle_INPROCESS_DELAY = initCellStyle(wb, HSSFColor.RED.index);
	    HSSFCellStyle cellStyle_COMPLETED = initCellStyle(wb, HSSFColor.GREEN.index);
	    
	    colorMap.put(colors[0], cellStyle_SCHEDULED);
	    colorMap.put(colors[1], cellStyle_INPROCESS);
	    colorMap.put(colors[2], cellStyle_INPROCESS_DELAY);
	    colorMap.put(colors[3], cellStyle_COMPLETED);
	    return colorMap;
	}
	
	/**
	 * 写活动内容
	 * @param materialCategory
	 * @param addTitle
	 * @param phaseKey
	 * @param jsonObject
	 * @param tempRow
	 * @param cellStyle
	 * @throws JSONException
	 * @author xucr
	 * @CreateDate 2020年9月25日
	 */
	private int writeActivityData(String materialCategory, 
			String addTitle, String phaseKey, JSONObject jsonObject,
			int row, HSSFSheet sheet, Map<String, HSSFCellStyle> colorMap) throws JSONException {
 		String [] materialCategorys = materialCategory.split(APQPProjectConstant.SPLITVALUE);
 		String[] phaseKeys = phaseKey.split(APQPProjectConstant.SPLITVALUE);
 		String[] addTitleKeys = addTitle.split(APQPProjectConstant.SPLITVALUE);
 		HSSFCell cell = null;
 		HSSFRow tempRow = null;
 		int maxRows = 1;
		for(int j = 0 ; j < materialCategorys.length; j++) {//外层：阶段
 			String key = materialCategorys[j].split(APQPPlanActivityService.MATERIALCATEGORY_SPLIT)[0].trim();
 			String pn = "";
			String supplier = "";
			String sqe = "";
			String completionStatus = "";
			String startDate = "";
			String url = "";
 			if(jsonObject.has(key)) {
 				JSONArray actArray = jsonObject.getJSONArray(key);
 				if(null != actArray && actArray.length() > 0) {//如果某个阶段有多条，则以多行形式展示
 					if(maxRows < actArray.length()) {
						maxRows = actArray.length();
					}
 					JSONObject actObj = null;
 					for(int y = 0 ; y < actArray.length(); y++) {
 						actObj = actArray.getJSONObject(y);
						tempRow = sheet.getRow(row + y);
						if(null == tempRow) {
							tempRow = sheet.createRow(row + y);
						}
 						
 						for(int z = addTitleKeys.length ; z < phaseKeys.length; z++) {//因为addTitleLeng这个长度是固定的，不是各个具体任务，无需循环
 		 					cell = tempRow.createCell(PROJECT_TABLE_MAP.size() + j*phaseKeys.length  +  z );
 		 					if(actObj.has(phaseKeys[z])) {
 		 	 					JSONObject actInfo = actObj.getJSONObject(phaseKeys[z]);
 		 	 					if(actInfo.has("pn"))
 		 	 						pn = actInfo.getString("pn");
 		 	 					if(actInfo.has("supplier"))
 		 	 						supplier = actInfo.getString("supplier");
 		 	 					if(actInfo.has("owner"))
 		 	 						sqe = actInfo.getString("owner");
 		 	 					if(actInfo.has("completionStatus"))
 		 	 						completionStatus = actInfo.getString("completionStatus");
 		 	 					if(actInfo.has("startDate")) {
 		 	 						startDate = actInfo.getString("startDate");
 		 	 					}
 		 	 					if(actInfo.has("url")) {
 		 	 						url = actInfo.getString("url");
 		 	 					}
 		 	 				} else {
 		 	 					//因为每一行数据中心，pn、supplier、sqe相同，因此无需重置，而不同的任务，完成情况不一直，所以在无值得情况下要重置
 		 	 	 				completionStatus = "";
 		 	 	 				startDate = "";
 		 	 	 				url = "";
 		 	 				}
 		 					/**
 		 					 * 在写入列时，各个数字的说明：
 		 					 * PROJECT_TABLE_MAP.size()：项目信息列，活动列在项目列之后，因此在写入活动列位置需要加上项目列数
 		 					 * j：代表第j个阶段
 		 					 * phaseKeys.length：代表每个阶段要写入的列数（包含固定列 + 循环列）
 		 					 * j*phaseKeys.length：代表第j个阶段，写入的数据列数
 		 					 * z：每个阶段中，固定列的列数，在写循环任务时，需要加上该列数
 		 					 * 
 		 					 * 
 		 					 * 设置Excel文本值换行主要代码设置样式： setWrapText(), 
 		 					 * 设置的文本值添加 \r\n字符使用：HSSFRichTextString()处理文本值
 		 					 * */
 		 					cell.setCellValue(startDate);
 		 					if(colors[0].equals(completionStatus)) {
 		 						cell.setCellStyle(colorMap.get(colors[0]));
 		 					} else if(colors[1].equals(completionStatus)) {
 		 						cell.setCellStyle(colorMap.get(colors[1]));
 		 					} else if(colors[2].equals(completionStatus)) {
 		 						cell.setCellStyle(colorMap.get(colors[2]));
 		 					} else if(colors[3].equals(completionStatus)) {
 		 						cell.setCellStyle(colorMap.get(colors[3]));
 		 						
 		 						//构造超链接
 		 						HSSFHyperlink link = new HSSFHyperlink(HSSFHyperlink.LINK_URL);
 		 						link.setAddress(url);
 		 						cell.setHyperlink(link);
 		 					}
 		 				}
 		 				//这里的三行，是增加列addTitle的显示
 		 				tempRow.createCell(PROJECT_TABLE_MAP.size() + j*phaseKeys.length).setCellValue(pn);
 		 				tempRow.createCell(PROJECT_TABLE_MAP.size() + j*phaseKeys.length + 1).setCellValue(supplier);
 		 				tempRow.createCell(PROJECT_TABLE_MAP.size() + j*phaseKeys.length + 2).setCellValue(sqe);
 					}
 				}
 			}
 		}
		return maxRows;
	}
	
	/**
	 * 设置软类型
	 * @param type
	 * @param softType
	 * @throws WTPropertyVetoException
	 * @author xucr
	 * @CreateDate 2020年8月13日
	 */
	public void setSoftType(Typed type,String softType) throws WTPropertyVetoException {
        TypedUtility.initTypeDefinitions();
        TypeDefinitionReference typeRef =  TypedUtility.getTypeDefinitionReference(softType);
        type.setTypeDefinitionReference(typeRef);
    }
	
	/**
	 * 查询机型名称
	 * @param partNumber
	 * @author xucr
	 * @throws WTException 
	 * @throws RemoteException 
	 * @throws JSONException 
	 * @CreateDate 2020年8月20日
	 */
	public JSONObject getModelName(String partNumber) throws RemoteException, WTException, JSONException {
		/**
		 * 即成品料号，模糊匹配， Design视图
		 * 返回成品料号+LCM产地
		 * 最新大版本：？？？ 最新大版本不一定是Design视图
		 * 
		 * 变更：
		 * 即成品料号，模糊匹配， Design视图+非废弃
		 * 
		 * 去重 new LatestConfigSpec().process(qr);//去重，取最新
		 * */
		QuerySpec qs = new QuerySpec(WTPart.class);
	    qs.setAdvancedQueryEnabled(true);
	    
	    //仅查询成品
		TypeDefinitionReference clientType = ClientTypedUtility.getTypeDefinitionReference("cn.tianma.FinishedGood");
		SearchCondition sc = new SearchCondition(WTPart.class,
				Typed.TYPE_DEFINITION_REFERENCE + "." + TypeDefinitionReference.KEY + "." + TypeDefinitionForeignKey.BRANCH_ID, 
				SearchCondition.EQUAL, clientType.getKey().getBranchId());
		qs.appendWhere(sc, new int[] { 0 });
		
//		//最新小版本
//		SearchCondition sc1 = new SearchCondition(WTPart.class,"iterationInfo.latest", SearchCondition.IS_TRUE, true);
//		qs.appendAnd();
//		qs.appendWhere(sc1, new int[] { 0 });
//		
//		//最新大版本
//		TMPartUtil.addSearchConditionLasterVersion(qs, WTPart.class,null);
		
		//Design视图
		View viewObj = ViewHelper.service.getView("Design");
		Long viewId = viewObj.getPersistInfo().getObjectIdentifier().getId();
		SearchCondition sc3 = new SearchCondition(WTPart.class, "view.key.id", SearchCondition.EQUAL, viewId);
		qs.appendAnd();
		qs.appendWhere(sc3, new int[] { 0 });
		
		//料号
		SearchCondition sc2 = new SearchCondition(WTPart.class,WTPart.NUMBER, SearchCondition.LIKE, "%" + partNumber + "%");
		qs.appendAnd();
		qs.appendWhere(sc2, new int[] { 0 });
		
		//非废弃
		SearchCondition sc4 = new SearchCondition(WTPart.class,"state.state", SearchCondition.NOT_EQUAL, "OBSOLESCENCE");
		qs.appendAnd();
		qs.appendWhere(sc4, new int[] { 0 });
		
		logger.info("getModelName sql>>>>" + qs.toString());
		QueryResult qr = PersistenceHelper.manager.find(qs);
		JSONObject obj = null;
		JSONArray array = new JSONArray();
		ReferenceFactory rf = new ReferenceFactory();
		
		qr = new LatestConfigSpec().process(qr);//去重，取最新
		while (qr.hasMoreElements()) {
			obj = new JSONObject();
			WTPart part = (WTPart) qr.nextElement();
			obj.put("partNumber", part.getNumber());
			obj.put("version", CommonPDMUtil.getVersion(part));
			obj.put("partOid", rf.getReferenceString(part));
			obj.put("lcmSite", TMUtil.conversion((String) IBAUtil.getIBAValue(part, "partNumberEffectiveSite")));
			obj.put("supplier", TMUtil.conversion((String) IBAUtil.getIBAValue(part, "partSupplier")));
			
			array.put(obj);
		}
		
		JSONObject rsult = ProjectUtil.respInfo(array, qr.size());
		
		return rsult;
	}
	
	/**
	 * 初始化apqp序列号
	 * @author xucr
	 * @throws WTException 
	 * @throws WTPropertyVetoException 
	 * @CreateDate 2020年8月27日
	 */
	public String initAPQPSequence() throws WTException, WTPropertyVetoException {
		/**
		 * 规则：
		 * 1、三位数
		 * 2、从001 开始，+1递增
		 * 3、每天重置
		 * */
		
		//判断当天序列是否存在，并重新计算
		String calendar = TMUtil.getnowaday("yyyyMMdd");
		APQPSequence se = queryAPQPSequence(calendar);
		Integer sequence = 1;
		if(null != se) {
			sequence = se.getSerialNumber() + 1;
		} else {
			se = APQPSequence.newAPQPSequence();
			se.setCalendar(calendar);
		}
		String serial = supply(sequence);
		
		//更新
		se.setSerialNumber(sequence);
		PersistenceHelper.manager.save(se);
		PersistenceHelper.manager.refresh(se);
		
		StringBuffer sb = new StringBuffer("APQP");
		return sb.append(calendar).append(serial).toString();
	}
	
	/**
	 * 构造三位有效序列,不足的以0补全
	 * @param sequence
	 * @return
	 * @author xucr
	 * @CreateDate 2020年8月27日
	 */
	private String supply(int sequence) {
		String sequenceStr = String.valueOf(sequence);
		int leng = sequenceStr.length();
		if(leng < SERIALLENGTH) {
			for(int i = 0 ; i < SERIALLENGTH - leng; i++) {
				sequenceStr = "0" + sequenceStr;
			}
		}
		return sequenceStr;
	}
	
	/**
	 * 查询APQPSequence序列号
	 * @param calendar
	 * @return
	 * @throws WTException
	 * @author xucr
	 * @CreateDate 2020年8月27日
	 */
	private APQPSequence queryAPQPSequence(String calendar) throws WTException {
		QuerySpec qs = new QuerySpec(APQPSequence.class);
	    qs.setAdvancedQueryEnabled(true);
	    SearchCondition sc1 = new SearchCondition(APQPSequence.class,APQPSequence.CALENDAR, SearchCondition.EQUAL, calendar);
	    qs.appendWhere(sc1, new int [] {0});
	    QueryResult qr = PersistenceHelper.manager.find(qs);
	    APQPSequence se = null;
	    while(qr.hasMoreElements()) {
	    	se = (APQPSequence) qr.nextElement();
	    }
	   return se;
	}
	
	

}
